package cn.cas.mango.service;

import cn.cas.mango.dto.HotChartValue;
import cn.cas.mango.dto.Message;
import cn.cas.mango.dto.param.QueryParam;
import cn.cas.mango.dto.WebSiteTypeInfo;
import cn.cas.mango.util.TimeUtil;
import cn.cas.mango.util.paramCheck.QueryParamCheckUtil;
import cn.cas.mango.util.RenderDateUtil;
import cn.cas.mango.util.RequestUtil.BuildRequest;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.aggregations.CalendarInterval;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.util.NamedValue;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
@Slf4j
public class HotAxisByAdvService {

  @Autowired
  private CountService countService;

  @Autowired
  private ConfigService config;
  @Autowired
  private BuildRequest buildRequest;

  private int monthShow = 2;

  private int getColorCast(Integer[] array, int key) {
    if (array.length == 0) {
      return 1;
    }
    int min = array[0];
    int max = array[array.length - 1];
    if (max - min == 0) {
      return 1;
    }
    int a = (int)(((double)(key - min) * 4) / (max - min) + 1);
    if (a == 5)
      a = 4;
    return a;
  }

  private int getColorCast(Float[] array, float key) {
    if (array.length == 0) {
      return 1;
    }
    float min = array[0];
    float max = array[array.length - 1];
    if (max - min == 0) {
      return 1;
    }
    int a = (int)(((double)(key - min) * 4) / (max - min) + 1);
    if (a == 5)
      a = 4;
    return a;
  }

  private int getColorCast(Double[] array, double key) {
    if (array.length == 0) {
      return 1;
    }
    double min = array[0];
    double max = array[array.length - 1];
    if (max - min == 0) {
      return 1;
    }
    int a = (int)(((double)(key - min) * 4) / (max - min) + 1);
    if (a == 5)
      a = 4;
    return a;
  }

  /**
   * 热度接口.
   */
  public Message getHotAxisByAdv(QueryParam queryParam)  {
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
    long start = System.currentTimeMillis();
    if (Strings.isBlank(queryParam.getStartDate())) {
      queryParam.setStartDate(
          simpleDateFormat.format(new Date().getTime() - 29 *  24 * 60 * 60 * 1000L));
    }
    if (Strings.isBlank(queryParam.getEndDate())) {
      queryParam.setEndDate(simpleDateFormat.format(new Date()));
    }
    Map<String, Object> errMessage = QueryParamCheckUtil.checkParam(queryParam, config.getPageSize());
    String isSuccess = (String) errMessage.get("isSuccess");
    if (!isSuccess.equals("ok")) {
      log.error(isSuccess);
      return Message.unSuccess(isSuccess);
    }
    queryParam = QueryParam.getFromFormData(errMessage);
    queryParam.setPageSize(0);
    final List<String> axisDay = RenderDateUtil.getDistanceDate(queryParam.getStartDate(),
        queryParam.getEndDate());
    final List<String> getDistanceMonth = RenderDateUtil.getDistanceMonth(axisDay);
    final List<String> getDistanceYear = RenderDateUtil.getDistanceYear(axisDay);
    final LinkedHashMap<String, List<String>> getDistanceYearMap = RenderDateUtil.getDistanceYearMap(
        axisDay);
    SearchRequest.Builder requestBuilder;
    if (queryParam.getQueryStr().contains("+") || queryParam.getQueryStr().contains("-")
      ) {
      requestBuilder = buildRequest.buildQueryStrRequest(queryParam);
    } else {
      requestBuilder = buildRequest.buildRequest(queryParam);
    }

    NamedValue<SortOrder> order = new NamedValue<>("_key", SortOrder.Asc);
    String field = "news_publicdate";
    requestBuilder
        .aggregations("type-day",
            aggBuilder ->
              aggBuilder.dateHistogram(
                    gram -> gram.field(field).calendarInterval(CalendarInterval.Day)
                        .format("yyyy-MM-dd")
                        .minDocCount(1).order(order))
                .aggregations("group_by_type",
                    a -> a.terms(t -> t.field("news_website_type").size(axisDay.size())))
        )
        .aggregations("count-day",
            aggBuilder -> aggBuilder.dateHistogram(
                gram -> gram.field(field).calendarInterval(CalendarInterval.Day)
                    .format("yyyy-MM-dd")
                    .minDocCount(1).order(order))
        )
        .aggregations("website-day",
            aggBuilder -> aggBuilder.dateHistogram(
                gram -> gram.field(field).calendarInterval(CalendarInterval.Day)
                    .format("yyyy-MM-dd")
                    .minDocCount(1).order(order))
                .aggregations("group_by_website",
                    a->a.terms(t->t.field("news_website").size(config.getWebsiteSize())))
        )
    ;
    if (getDistanceMonth.size() > monthShow) {
      requestBuilder
          .aggregations("count-month",
              aggBuilder -> aggBuilder.dateHistogram(
                  gram -> gram.field(field).calendarInterval(CalendarInterval.Month)
                      .format("yyyy-MM")
                      .minDocCount(1).order(order))
          )
          .aggregations("website-month",
              aggBuilder -> aggBuilder.dateHistogram(
                      gram -> gram.field(field).calendarInterval(CalendarInterval.Month)
                          .format("yyyy-MM")
                          .minDocCount(1).order(order))
                  .aggregations("group_by_website",
                      a->a.terms(t->t.field("news_website").size(config.getWebsiteSize())))
          )
      ;
    }
    if (axisDay.size() > 365 * 3) {
      requestBuilder
          .aggregations("count-year",
              aggBuilder -> aggBuilder.dateHistogram(
                  gram -> gram.field(field).calendarInterval(CalendarInterval.Year)
                      .format("yyyy")
                      .minDocCount(1).order(order)))
          .aggregations("website-year",
              aggBuilder -> aggBuilder.dateHistogram(
                      gram -> gram.field(field).calendarInterval(CalendarInterval.Year)
                          .format("yyyy")
                          .minDocCount(1).order(order))
                  .aggregations("group_by_website",
                      a->a.terms(t->t.field("news_website").size(config.getWebsiteSize())))
          )
      ;
    }
    SearchRequest searchRequest = requestBuilder.build();
    String queryJsonStr = searchRequest.toString().split("typed_keys=true")[1];
    JSONObject queryJson = JSONObject.parseObject(queryJsonStr);
    log.info("Search Request Json:{}", queryJson);
    RestTemplateBuilder builder = new RestTemplateBuilder();
    RestTemplate restTemplate = builder.basicAuthentication(config.getUsername(), config.getPassword()).build();
    log.info("Start Request:{}", System.currentTimeMillis() - start);
    String url = "http://" + config.getHost() + ":" + config.getPort() + "/" + config.getIndex() + "/_search";
    ResponseEntity<JSONObject> responseEntity = restTemplate.postForEntity(url, queryJson,
        JSONObject.class);
    log.info("Get Response:{}", System.currentTimeMillis() - start);
    JSONObject responseJson = Objects.requireNonNull(responseEntity.getBody())
        .getJSONObject("aggregations");
    final Map<Integer, String> colorMap = config.getColorMap();
    final LinkedHashMap<String, List<String>> monthMap = RenderDateUtil.getDistanceMonthMap(
        axisDay);
    //处理按天统计数据
    JSONArray countDayArray = responseJson.getJSONObject("count-day").getJSONArray("buckets");
    Map<String, Integer> dayCountMap = new HashMap<>();
    LinkedHashMap<String, Integer> dayTotalMap = this.countService.getDayCountMap(
        queryParam.getStartDate(), queryParam.getEndDate());
    int dayMinCount;
    int dayMaxCount;
    for (Object row : countDayArray) {
      JSONObject rowJson = (JSONObject) row;
      String day = rowJson.getString("key_as_string");
      Integer count = rowJson.getInteger("doc_count");
      dayCountMap.put(day, count);
    }
    List<HotChartValue> countDayList = new ArrayList<>();
    List<HotChartValue> hotDayList = new ArrayList<>();
    List<Integer> dayCount = new ArrayList<>();
    List<Float> dayHot = new ArrayList<>();
    for (String day : axisDay) {
      HotChartValue countValue = new HotChartValue();
      HotChartValue hotValue = new HotChartValue();
      countValue.setDate(day);
      hotValue.setDate(day);
      if (dayCountMap.get(day) != null) {
        countValue.setValue(dayCountMap.get(day));
        dayCount.add(dayCountMap.get(day));
        float hotCount = (float) dayCountMap.get(day)
            / dayTotalMap.get(day);
        hotValue.setValue(hotCount * 100);
        dayHot.add(hotCount * 100);
      } else {
        countValue.setValue(0);
        dayCount.add(0);
        hotValue.setValue(0.0);
        dayHot.add(0.0F);
      }
      countDayList.add(countValue);
      hotDayList.add(hotValue);
    }
    Integer[] countArray = new Integer[dayCount.size()];
    countArray = dayCount.toArray(countArray);
    Arrays.sort(countArray);
    dayMaxCount = countArray[countArray.length - 1];
    dayMinCount = countArray[0];

    for (HotChartValue value : countDayList) {
      int value1 = (int)value.getValue();
      int a = getColorCast(countArray, value1);
      value.setColor(colorMap.get(a));
    }
    Float[] hotArray = new Float[dayHot.size()];
    hotArray = dayHot.toArray(hotArray);
    Arrays.sort(hotArray);

    for (HotChartValue value : hotDayList) {
      float value1 = Float.parseFloat(String.valueOf(value.getValue()));
      int a = getColorCast(hotArray, value1);
      value.setColor(colorMap.get(a));

    }
    log.info("数量按天处理End:{}", System.currentTimeMillis() - start);
    //处理按月统计数据
    List<HotChartValue> monthCountList = new ArrayList<>();
    int monthMinCount = 0;
    int monthMaxCount = 0;
    List<HotChartValue> monthHotList = new ArrayList<>();
    if (getDistanceMonth.size() > monthShow) {
      JSONArray countMonthArray = responseJson.getJSONObject("count-month").getJSONArray("buckets");
      Map<String, Integer> monthCountMap = new HashMap<>();
      for (Object row : countMonthArray) {
        JSONObject rowJson = (JSONObject) row;
        String day = rowJson.getString("key_as_string");
        Integer count = rowJson.getInteger("doc_count");
        monthCountMap.put(day, count);
        if (count > monthMaxCount) {
          monthMaxCount = count;
        }
        if (monthMinCount == 0) {
          monthMinCount = count;
        }
        if (count < monthMinCount) {
          monthMinCount = count;
        }
      }

      List<Integer> monthCount = new ArrayList<>();
      for (String day : getDistanceMonth) {
        HotChartValue countValue = new HotChartValue();
        countValue.setDate(day);
        if (monthCountMap.get(day) != null) {
          countValue.setValue(monthCountMap.get(day));
          monthCount.add(monthCountMap.get(day));
        } else {
          countValue.setValue(0);
          monthCount.add(0);
        }
        monthCountList.add(countValue);
      }

      Integer[] monthArray = new Integer[monthCount.size()];
      monthArray = monthCount.toArray(monthArray);
      Arrays.sort(monthArray);

      for (HotChartValue value : monthCountList) {
        int value1 = (int) value.getValue();
        int a = getColorCast(monthArray, value1);
        value.setColor(colorMap.get(a));
      }

      //处理按月统计热度数据（将天热度数据加和）
      List<Float> monthHot = new ArrayList<>();
      for (String month : monthMap.keySet()) {
        float hotValue = 0.0f;
        for (String day : monthMap.get(month)) {
          for (HotChartValue value : hotDayList) {
            if (value.getDate().equals(day)) {
              hotValue += Float.parseFloat(String.valueOf(value.getValue()));
            }
          }
        }
        HotChartValue hotChartValue = new HotChartValue();
        hotChartValue.setDate(month);
        hotChartValue.setValue(hotValue);
        monthHotList.add(hotChartValue);
        monthHot.add(hotValue);
      }

      Float[] monthHotArray = new Float[monthHot.size()];
      monthHotArray = monthHot.toArray(monthHotArray);
      Arrays.sort(monthHotArray);

      for (HotChartValue value : monthHotList) {
        float value1 = Float.parseFloat(String.valueOf(value.getValue()));
        int a = getColorCast(monthHotArray, value1);
        value.setColor(colorMap.get(a));
      }
    }
    log.info("数量按月处理End:{}", System.currentTimeMillis() - start);
    // 处理按年统计数据
    List<HotChartValue> yearCountList = new ArrayList<>();
    List<HotChartValue> yearHotList = new ArrayList<>();
    int yearMinCount = 0;
    int yearMaxCount = 0;
    if (axisDay.size() > 365 * 3) {
      JSONArray countYearArray = responseJson.getJSONObject("count-year").getJSONArray("buckets");
      Map<String, Integer> yearCountMap = new HashMap<>();
      for (Object row : countYearArray) {
        JSONObject rowJson = (JSONObject) row;
        String day = rowJson.getString("key_as_string");
        Integer count = rowJson.getInteger("doc_count");
        yearCountMap.put(day, count);
        if (count > yearMaxCount) {
          yearMaxCount = count;
        }
        if (yearMinCount == 0) {
          yearMinCount = count;
        }
        if (count < yearMinCount) {
          yearMinCount = count;
        }
      }
      yearCountList = new ArrayList<>();
      List<Integer> yearCount = new ArrayList<>();
      for (String day : getDistanceYear) {
        HotChartValue countValue = new HotChartValue();
        HotChartValue hotValue = new HotChartValue();
        countValue.setDate(day);
        hotValue.setDate(day);
        if (yearCountMap.get(day) != null) {
          countValue.setValue(yearCountMap.get(day));
          yearCount.add(yearCountMap.get(day));
        } else {
          countValue.setValue(0);
          yearCount.add(0);
        }
        yearCountList.add(countValue);
      }

      Integer[] yearArray = new Integer[yearCount.size()];
      yearArray = yearCount.toArray(yearArray);
      Arrays.sort(yearArray);

      for (HotChartValue value : yearCountList) {
        int value1 = (int)value.getValue();
        int a = getColorCast(yearArray, value1);
        value.setColor(colorMap.get(a));
      }

      //处理按年统计热度数据（将天热度数据加和）
      List<Float> yearHot = new ArrayList<>();
      for (String year : getDistanceYearMap.keySet()) {
        float hotValue = 0.0f;
        for (String day : getDistanceYearMap.get(year)) {
          for (HotChartValue value : hotDayList) {
            if (value.getDate().equals(day)) {
              hotValue += Float.parseFloat(String.valueOf(value.getValue()));
            }
          }
        }
        HotChartValue hotChartValue = new HotChartValue();
        hotChartValue.setDate(year);
        hotChartValue.setValue(hotValue);
        yearHotList.add(hotChartValue);
        yearHot.add(hotValue);
      }

      Float[] yearHotArray = new Float[yearHot.size()];
      yearHotArray = yearHot.toArray(yearHotArray);
      Arrays.sort(yearHotArray);

      for (HotChartValue value : yearHotList) {
        float value1 = Float.parseFloat(String.valueOf(value.getValue()));
        int a = getColorCast(yearHotArray, value1);
        value.setColor(colorMap.get(a));
      }
    }
    log.info("数量按年处理End:{}", System.currentTimeMillis() - start);
    // 按日处理类型
    JSONArray typeDayArray = responseJson.getJSONObject("type-day").getJSONArray("buckets");
    List<WebSiteTypeInfo> dayWebSiteTypeInfos = new ArrayList<>();
    for (Object object : typeDayArray) {
      JSONObject groupByType = ((JSONObject) object).getJSONObject("group_by_type");
      JSONArray innerBuckets = groupByType.getJSONArray("buckets");
      String innerDate = ((JSONObject) object).getString("key_as_string");
      for (Object bucket : innerBuckets) {
        WebSiteTypeInfo info = new WebSiteTypeInfo();
        info.setName(((JSONObject) bucket).getString("key"));
        info.setDate(innerDate);
        info.setCount(
            ((float) ((JSONObject) bucket).getLong("doc_count") / dayTotalMap.get(innerDate)
                * 100));
        dayWebSiteTypeInfos.add(info);
      }
    }
    Map<String, List<WebSiteTypeInfo>> typeDayMap = new HashMap<>();
    for (WebSiteTypeInfo info : dayWebSiteTypeInfos) {
      if (typeDayMap.get(info.getName()) != null) {
        typeDayMap.get(info.getName()).add(info);
      } else {
        List<WebSiteTypeInfo> list = new ArrayList<>();
        list.add(info);
        typeDayMap.put(info.getName(), list);
      }
    }
    String[] types = new String[]{"OVERSEAS", "WEBSITE", "HMT", "GOV", "ANTI"};
    for (String type : types) {
      boolean have = false;
      for (String name : typeDayMap.keySet()) {
        if (name.equals(type)) {
          have = true;
          break;
        }
      }
      if (!have) {
        typeDayMap.put(type, new ArrayList<>());
      }
    }
    int dayAlert = 0;
    List<JSONObject> seriesDay = new ArrayList<>();
    List<String> legendDay = new ArrayList<>();

    for (String type : typeDayMap.keySet()) {
      legendDay.add(config.getWebSiteTypeName(type));
      JSONObject seriesObject = new JSONObject();
      seriesObject.put("news_website_type", type);
      seriesObject.put("name", config.getWebSiteTypeName(type));
      List<Double> countList = new ArrayList<>();
      List<WebSiteTypeInfo> infos = typeDayMap.get(type);
      for (String time : axisDay) {
        boolean fill = true;
        for (WebSiteTypeInfo info : infos) {
          if (time.equals(info.getDate())) {
            countList.add(info.getCount());
            dayAlert += info.getCount();
            fill = false;
          }
        }
        if (fill) {
          countList.add(0.0);
        }
      }
      seriesObject.put("data", countList);
      seriesDay.add(seriesObject);
    }

    log.info("按天处理类型End:{}", System.currentTimeMillis() - start);
    // 按月处理类型
    List<JSONObject> seriesMonth = new ArrayList<>();
    List<String> legendMonth = new ArrayList<>();
    int monthAlert = 0;
    if (getDistanceMonth.size() > monthShow) {
      Map<String, List<WebSiteTypeInfo>> typeMonthMap = new HashMap<>();
      for (String type : typeDayMap.keySet()) {
        List<WebSiteTypeInfo> monthWebSiteTypeInfos = new ArrayList<>();
        for (String month : monthMap.keySet()) {
          WebSiteTypeInfo webSiteTypeInfo = new WebSiteTypeInfo();
          webSiteTypeInfo.setDate(month);
          webSiteTypeInfo.setName(type);
          float count = 0F;
          for (WebSiteTypeInfo dayInfo : typeDayMap.get(type)) {
            for (String day : monthMap.get(month)) {
              if (dayInfo.getDate().equals(day) && type.equals(dayInfo.getName())) {
                count += dayInfo.getCount();
              }
            }
            webSiteTypeInfo.setCount(count);
          }
          monthWebSiteTypeInfos.add(webSiteTypeInfo);
        }
        typeMonthMap.put(type, monthWebSiteTypeInfos);
      }

      for (String type : typeMonthMap.keySet()) {
        legendMonth.add(config.getWebSiteTypeName(type));
        JSONObject seriesObject = new JSONObject();
        seriesObject.put("news_website_type", type);
        seriesObject.put("name", config.getWebSiteTypeName(type));
        List<Double> countList = new ArrayList<>();
        List<WebSiteTypeInfo> infos = typeMonthMap.get(type);
        for (String time : getDistanceMonth) {
          boolean fill = true;
          for (WebSiteTypeInfo info : infos) {
            if (time.equals(info.getDate())) {
              countList.add(info.getCount());
              monthAlert += info.getCount();
              fill = false;
            }
          }
          if (fill) {
            countList.add(0.0);
          }
        }
        seriesObject.put("data", countList);
        seriesMonth.add(seriesObject);
      }
    }
    log.info("按月处理类型End:{}", System.currentTimeMillis() - start);

    // 按年处理类型
    List<JSONObject> seriesYear = new ArrayList<>();
    List<String> legendYear = new ArrayList<>();
    int yearAlert = 0;
    if (axisDay.size() > 365 * 3) {
      Map<String, List<WebSiteTypeInfo>> typeYearMap = new HashMap<>();
      for (String type : typeDayMap.keySet()) {
        List<WebSiteTypeInfo> yearWebSiteTypeInfos = new ArrayList<>();
        for (String year : getDistanceYearMap.keySet()) {
          WebSiteTypeInfo webSiteTypeInfo = new WebSiteTypeInfo();
          webSiteTypeInfo.setDate(year);
          webSiteTypeInfo.setName(type);
          float count = 0F;
          for (WebSiteTypeInfo dayInfo : typeDayMap.get(type)) {
            for (String day : getDistanceYearMap.get(year)) {
              if (dayInfo.getDate().equals(day) && type.equals(dayInfo.getName())) {
                count += dayInfo.getCount();
              }
            }
            webSiteTypeInfo.setCount(count);
          }
          yearWebSiteTypeInfos.add(webSiteTypeInfo);
        }
        typeYearMap.put(type, yearWebSiteTypeInfos);
      }

      for (String type : typeYearMap.keySet()) {
        legendYear.add(config.getWebSiteTypeName(type));
        JSONObject seriesObject = new JSONObject();
        seriesObject.put("news_website_type", type);
        seriesObject.put("name", config.getWebSiteTypeName(type));
        List<Double> countList = new ArrayList<>();
        List<WebSiteTypeInfo> infos = typeYearMap.get(type);
        for (String time : getDistanceYear) {
          boolean fill = true;
          for (WebSiteTypeInfo info : infos) {
            if (time.equals(info.getDate())) {
              countList.add(info.getCount());
              yearAlert += info.getCount();
              fill = false;
            }
          }
          if (fill) {
            countList.add(0.0);
          }
        }
        seriesObject.put("data", countList);
        seriesYear.add(seriesObject);
      }
    }
    log.info("按年处理类型End:{}", System.currentTimeMillis() - start);
    Map<String, Object> statisticDay = new HashMap<>();
    statisticDay.put("series", seriesDay);
    statisticDay.put("xAxis", axisDay);
    statisticDay.put("legend", legendDay);
    Map<String, Object> statisticMonth = new HashMap<>();
    statisticMonth.put("series", seriesMonth);
    statisticMonth.put("xAxis", getDistanceMonth);
    statisticMonth.put("legend", legendMonth);
    Object[] statistic;
    String[] tag;
    double[] alert;
    if (axisDay.size() > 365 * 3) {
      Map<String, Object> statisticYear = new HashMap<>();
      statisticYear.put("series", seriesYear);
      statisticYear.put("xAxis", getDistanceYear);
      statisticYear.put("legend", legendYear);
      statistic = new Map[3];
      statistic[0] = statisticDay;
      statistic[1] = statisticMonth;
      statistic[2] = statisticYear;
      tag = new String[]{"日", "月", "年"};
      alert = new double[]{(double) dayAlert / axisDay.size(),
          (double) monthAlert / getDistanceMonth.size(),
          (double) yearAlert / getDistanceYear.size()};
    } else if (getDistanceMonth.size() < monthShow + 1) {
      statistic = new Map[1];
      statistic[0] = statisticDay;
      tag = new String[]{"日"};
      alert = new double[]{(double) dayAlert / axisDay.size()};
    } else {
      statistic = new Map[2];
      statistic[0] = statisticDay;
      statistic[1] = statisticMonth;
      tag = new String[]{"日", "月"};
      alert = new double[]{(double) dayAlert / axisDay.size(),
          (double) monthAlert / getDistanceMonth.size()};
    }
    Map<String, Object> typeStatInfo = new HashMap<>();
    typeStatInfo.put("statistic", statistic);
    typeStatInfo.put("tag", tag);
    typeStatInfo.put("alert", alert);
    LinkedHashMap<String, Object> map = new LinkedHashMap<>();
    long end = System.currentTimeMillis();
    map.put("time", end - start);
    map.put("typeStatInfo", typeStatInfo);
    Map<String, Object> countStatInfo = new HashMap<>();
    double[] countAlert;
    if (axisDay.size() > 365 * 3) {
      countStatInfo.put("statistic", new List[]{
          countDayList, monthCountList, yearCountList
      });
      countAlert = new double[]{
          (double) (dayMaxCount + dayMinCount) / 2, (double) (monthMaxCount + monthMinCount) / 2,
          (double) (yearMaxCount + yearMinCount) / 2};

    } else if (getDistanceMonth.size() < monthShow + 1) {
      countStatInfo.put("statistic", new List[]{countDayList});
      countAlert = new double[]{(double) (dayMaxCount + dayMinCount) / 2};
    } else {
      countStatInfo.put("statistic", new List[]{
          countDayList, monthCountList
      });
      countAlert = new double[]{
          (double) (dayMaxCount + dayMinCount) / 2, (double) (monthMaxCount + monthMinCount) / 2
      };
    }
    countStatInfo.put("alert", countAlert);
    countStatInfo.put("tag", tag);
    map.put("countStatInfo", countStatInfo);
    Map<String, Object> hotStatInfo = new HashMap<>();
    if (axisDay.size() > 365 * 3) {
      hotStatInfo.put("statistic", new List[]{
          hotDayList, monthHotList, yearHotList
      });
      hotStatInfo.put("alert", new double[]{
          (double) (dayMaxCount + dayMinCount) / 2, (double) (monthMaxCount + monthMinCount) / 2,
          (double) (yearMaxCount + yearMinCount) / 2
      });
    } else if (getDistanceMonth.size() < monthShow + 1) {
      hotStatInfo.put("statistic", new List[]{
          hotDayList
      });
      hotStatInfo.put("alert", new double[]{
          (double) (dayMaxCount + dayMinCount) / 2
      });
    } else {
      hotStatInfo.put("statistic", new List[]{
          hotDayList, monthHotList
      });
      hotStatInfo.put("alert", new double[]{
          (double) (dayMaxCount + dayMinCount) / 2, (double) (monthMaxCount + monthMinCount) / 2
      });
    }
    hotStatInfo.put("tag", tag);
    map.put("hotStatInfo", hotStatInfo);

    JSONObject source = new JSONObject();
    source.put("alert", countAlert);
    source.put("tag", tag);
    source.put("statistic", wrapWebsite(axisDay, getDistanceMonth,
        getDistanceYear, responseJson));
    map.put("sourceStatInfo", source);
    map.put("queryStr", queryParam.getQueryStr());
    log.info("Send Response:{}", System.currentTimeMillis() - start);
    return Message.builder().code(200).message("success").data(map).build();
  }

  private Map<String, JSONObject> wrapArray2Map(JSONArray bucketsArray) {
    Map<String, JSONObject> map = new HashMap<>();
    for (Object o: bucketsArray) {
      JSONObject info = (JSONObject) o;
      map.put(info.getString("key_as_string"), info);
    }
    return map;
  }


  private JSONObject processWebSite(JSONObject responseJson, String dateType,
                                    List<String> dates) {
    JSONObject dateRet = new JSONObject();
    JSONArray dateBucketsArray = responseJson.getJSONObject(dateType).getJSONArray("buckets");
    Map<String, JSONObject> dateJsonMap = wrapArray2Map(dateBucketsArray);
    dateRet.put("xAxis", dates);
    List<List<JSONObject>> seriesList = new ArrayList<>();
    for (String date: dates) {
      if (dateJsonMap.containsKey(date)) {
        JSONObject info = dateJsonMap.get(date);
        JSONObject groupByWebsite = info.getJSONObject("group_by_website");
        int otherCount = groupByWebsite.getInteger("sum_other_doc_count");
        JSONArray buckets = groupByWebsite.getJSONArray("buckets");
        List<JSONObject> seriesItem = new ArrayList<>();

        for (Object o: buckets) {
          JSONObject sourceItem = (JSONObject) o;
          JSONObject wrapInfo = new JSONObject();
          wrapInfo.put("news_website", sourceItem.get("key"));
          wrapInfo.put("value", sourceItem.get("doc_count"));
          seriesItem.add(wrapInfo);
        }
        if (otherCount > 0) {
          JSONObject other = new JSONObject();
          other.put("news_website", "其他");
          other.put("value", otherCount);
          seriesItem.add(other);
        }
        seriesList.add(seriesItem);
      } else {
        seriesList.add(new ArrayList<>());
      }
    }
    dateRet.put("series", seriesList);
    return dateRet;
  }

  private List<JSONObject> wrapWebsite(List<String> axisDay,
                                       List<String> getDistanceMonth,
                                       List<String> getDistanceYear,
                                       JSONObject responseJson) {
    List<JSONObject> ret = new ArrayList<>();

    // 按日处理website
    TimeUtil timeUtil = new TimeUtil();
    timeUtil.setStart();
    ret.add(processWebSite(responseJson, "website-day", axisDay));

    log.info("按日处理website结束, 花费{}s", timeUtil.getCost());
    if (getDistanceMonth.size() > monthShow) {
      timeUtil.setStart();
      ret.add(processWebSite(responseJson, "website-month", getDistanceMonth));
      log.info("按月处理website结束, 花费{}s", timeUtil.getCost());
    }

    if (axisDay.size() > 365 * 3) {
      timeUtil.setStart();
      ret.add(processWebSite(responseJson, "website-year", getDistanceYear));
      log.info("按年处理website结束, 花费{}s", timeUtil.getCost());
    }
    return ret;
  }



}
